/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"fmt"
	"gopkg.in/yaml.v3"
	"log"
	"os"
	"path/filepath"
	"strings"
	"text/template"

	"github.com/spf13/cobra"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "openhis-config",
	Short: "生成配置文件",
	Long: `根据variable.yaml 和模板目录config 生成 院版HIS 部署配置文件. 

For example:

	./openhis-config.exe 
`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("开始生成配置文件")
		genConfig()
	},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func init() {
	// Here you will define your flags and configuration settings.
	// Cobra supports persistent flags, which, if defined here,
	// will be global for your application.

	// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.openhis-config.yaml)")

	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	//rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func genConfig() {
	var variable Variable

	// 检查文件类型是否是 .yaml 或 .yml
	if configFile != "" {
		ext := strings.ToLower(filepath.Ext(configFile))
		if ext != ".yaml" && ext != ".yml" {
			log.Fatalf("错误: 配置文件必须是 YAML 格式 (.yaml 或 .yml)，但收到的是 %s", ext)
		}
	} else {
		configFile = "./variable.yaml"
	}

	if outPath == "" {
		outPath = "./Web"
	}

	data, err := os.ReadFile(configFile)
	if err != nil {
		log.Fatalf("error: %v", err)
	}
	// 解析 YAML 到结构体
	err = yaml.Unmarshal(data, &variable)
	if err != nil {
		log.Fatalf("error: %v", err)
	}

	fmt.Println("DatabaseHost is：" + variable.DatabaseHost)

	// 要遍历的目录路径
	dirPath := "./config"

	// 回调函数，处理每个文件或目录
	err = filepath.Walk(dirPath, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			fmt.Println(err) // 打印错误信息
			return err       // 返回错误，可以决定是否继续遍历
		}
		if info.IsDir() {
			fmt.Printf("Directory: %s\n", path)
		} else if filepath.Ext(info.Name()) == ".tmpl" {
			fmt.Printf("File temp: %s\n", path)
			err := RenderTemplate(variable, path, outPath)
			if err != nil {
				fmt.Println("filepath.Walk() RenderTemplate returned:", err)
				return err
			}

		}
		return nil // 继续遍历
	})

	if err != nil {
		fmt.Println("filepath.Walk() returned:", err)
	}
}

func RenderTemplate(variable Variable, templatePath, outputBaseDir string) error {
	// 生成输出路径
	relativePath, err := filepath.Rel("./config", templatePath)
	if err != nil {
		return fmt.Errorf("无法解析相对路径: %v", err)
	}
	var outputPath string
	if filepath.Base(templatePath) == "install.ps1.tmpl" {
		// 如果是 install.ps1.tmpl，则输出到当前目录，并命名为 3_install.ps1
		outputPath = "./3_install.ps1"
	} else {
		outputPath = filepath.Join(outputBaseDir, strings.Replace(relativePath, ".tmpl", "", 1))
	}
	// 确保输出文件所在目录存在
	outputDir := filepath.Dir(outputPath)
	err = os.MkdirAll(outputDir, os.ModePerm)
	if err != nil {
		return fmt.Errorf("创建目录失败: %v", err)
	}

	// 读取模板文件
	tmplBytes, err := os.ReadFile(templatePath)
	if err != nil {
		return fmt.Errorf("读取模板文件失败: %v", err)
	}

	// 解析模板
	t, err := template.New("template").Parse(string(tmplBytes))
	if err != nil {
		return fmt.Errorf("解析模板失败: %v", err)
	}

	// 创建输出文件，覆盖已存在的文件
	outputFile, err := os.Create(outputPath)
	if err != nil {
		return fmt.Errorf("创建输出文件失败: %v", err)
	}
	defer outputFile.Close()

	// 渲染模板到输出文件
	err = t.Execute(outputFile, variable)
	if err != nil {
		return fmt.Errorf("渲染模板失败: %v", err)
	}

	fmt.Printf("Template rendered and output file created: %s\n", outputPath)
	return nil
}
